package com.cw.utils.web;


import com.cw.utils.json.GsonBUILDERUtil;
import com.cw.utils.json.JsonValueTrimUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;

import javax.servlet.ReadListener;
import javax.servlet.ServletInputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * @author 陈伟
 * @Date: 2022/08/24 17:38
 * @Description: s1、去除参数前后空格
 * @Version s1.0
 **/
public class ParameterRequestWrapper extends HttpServletRequestWrapper {
    private static Logger logger = LoggerFactory.getLogger(ParameterRequestWrapper.class);

    private Map<String,String[]> params = new HashMap<>();

    public ParameterRequestWrapper(HttpServletRequest request){
        super(request);
        //将参数表，赋予给当前的Map以便于持有request中的参数
        Map<String,String[]> requestMap = request.getParameterMap();
        this.params.putAll(requestMap);
        this.modifyParameterValues();
    }

    /*
     * @Author 陈伟
     * @Date 2022/8/24 17:45
     * @description 重写getInputStream方法，post类型的请求参数必须通过流才能获取到值
      * @param:
     * @Return javax.servlet.ServletInputStream
     */
    @Override
    public ServletInputStream getInputStream() throws IOException {
        //非json类型，直接返回
        String contentType = super.getHeader(HttpHeaders.CONTENT_TYPE);
        if(contentType==null){
            return super.getInputStream();
        }
        contentType =contentType.replace(" ", "").toUpperCase();
        if (!contentType.contains(MediaType.APPLICATION_JSON_VALUE.toUpperCase())) {//NOSONAR
            return super.getInputStream();
        }
        //为空，直接返回
        String json = IOUtils.toString(super.getInputStream(),StandardCharsets.UTF_8.name());
        if(StringUtils.isEmpty(json)){
            return super.getInputStream();
        }
        Object resultObject = JsonValueTrimUtil.jsonStrTrim(json);//这里处理的是json传参的参数
        String jsonResult = GsonBUILDERUtil.GSON_BUILDER_COMMON.toJson(resultObject);
        ByteArrayInputStream bis = new ByteArrayInputStream(jsonResult.getBytes(StandardCharsets.UTF_8));
        return new CustomServletInputStream(bis);
    }
    /*
     * @Author 陈伟
     * @Date 2022/8/24 18:02
     * @description 将parameter的值去除空格后重写回去
      * @param:
     * @Return void
     */
    private void modifyParameterValues(){
        Set<String> set  = params.keySet();
        Iterator<String> it = set.iterator();
        while(it.hasNext()){
            String key = it.next();
            String[] values = params.get(key);
            values[0] = values[0].trim();//去除前后空格
            //values[0] = JsonpUtil.clean(values[0]);//xss
            //values[0] = xss(values[0]);//处理xss
            params.put(key,values);
        }
    }

    @Override
    // 重写getParameter，代表参数从当前类中的map获取
    public String getParameter(String name) {
        String[] values = params.get(name);
        if (values == null || values.length == 0) {
            return null;
        }
        return values[0];
    }

    @Override
    public String[] getParameterValues(String name) {// 同上
        return params.get(name);
    }

    class CustomServletInputStream extends ServletInputStream {
        private ByteArrayInputStream bis;
        public CustomServletInputStream(ByteArrayInputStream bis){
            this.bis = bis;
        }
        @Override
        public int read() throws IOException {
            return bis.read();//NOSONAR
        }

        @Override
        public int readLine(byte[] b, int off, int len) throws IOException {
            return super.readLine(b, off, len);
        }

        //@Override
        public boolean isFinished() {
            return false;
        }

        //@Override
        public boolean isReady() {
            return false;
        }

        //@Override
        public void setReadListener(ReadListener readListener) {

        }
    }

}